<template>
  <div class="OneMap">
    <!-- 地图图层 -->
    <div class="map-wrapper-1" ref="mapDOM"></div>
    <!-- 弹窗组件 -->
    <bullet-box-sensor class="bullet"
      ref="msgFormSensor"
      :dataOutput="dataOutput"
      @closeBullet="closeBulletChange"
    ></bullet-box-sensor>
    <!-- 地图基本要素 -->
    <div class="position-bar-container-1">
      <div id="scale-line-container-1"></div>
      <div class="zoom-label-contaienr">级别:{{ zoom }}</div>
      <div class="coordinate-lebel-contaienr">
        <div class="lgtd-container">经度:{{ lgtd }}</div>
        <div class="lttd-container">纬度:{{ lttd }}</div>
      </div>
    </div>
    <!-- 图例显示 -->
    <div class="map-legend"></div>
    <!-- 指北针显示 -->
    <div class="map-compass"></div>
  </div>
</template>

<script>
import { Map, View, Overlay } from "ol";
import TileLayer from "ol/layer/Tile";
import XYZ from "ol/source/XYZ";
import { GeoJSON } from "ol/format";
import { defaults as defaultControls } from "ol/control";
import {
  Fill,
  Style,
  Stroke,
  Text,
  Icon,
  Circle as CircleStyle
} from "ol/style";
import ScaleLine from "ol/control/ScaleLine";
import VectorSource from "ol/source/Vector";
import VectorLayer from "ol/layer/Vector";
import Feature from "ol/Feature.js";
import Point from "ol/geom/Point.js";
import { fromExtent } from "ol/geom/Polygon";
import LinearRing from "ol/geom/LinearRing.js";
import { unByKey } from "ol/Observable.js";
import { getVectorContext } from "ol/render.js";
import { easeOut } from "ol/easing.js";
import { SensorArea } from "../../../../api/gis/layer";
import BoundaryAreaJson from "../../../../../static/新疆维吾尔自治区.json";
import BulletBoxSensor from "./BulletBox/BulletBoxSensor.vue";
import { listener } from "@/utils/listener";
import MaskFilter from "../../../../utils/gis/Mask";

let intervalKey;
let defaultZoom = 6;
let defaultCenter = [85.06,42.95];

export default {
  name: "OneMap",
  components: {
    BulletBoxSensor
  },
  data() {
    return {
      // map: null,
      dataOutput: {},
      zoom: 0,
      lgtd: 0,
      lttd: 0
    };
  },
  mounted() {
    this.handleMapInit();
    this.gisElement();
    listener.listen("/home", this.resetViewer);
  },
  beforeDestroy() {
    if (intervalKey) {
      clearInterval(intervalKey);
    }
    listener.unlisten("/home", this.resetViewer);
    this.dispose();
  },
  methods: {
    dispose() {
      const layers = this.map.getLayers();
      while (layers.getLength() > 0) {
        const layer = layers.item(0);
        if (layer.get("layerSourceType") === "VECTOR") {
          layer.getSource().clear();
        }
        layer.getRenderer().dispose();
        layer.setSource(null);
        this.map.removeLayer(layer);
      }
      this.map.setTarget(null);
    },
    gisElement() {
      const map = this.map;
      const scaleLine = new ScaleLine({
        target: "scale-line-container-1",
        units: "metric"
      });
      map.addControl(scaleLine);
      map.on("pointermove", e => {
        const coordinate = e.coordinate;
        this.lgtd = coordinate[0].toFixed(6);
        this.lttd = coordinate[1].toFixed(6);
      });
      map.on("moveend", () => {
        this.zoom = Math.round(this.map.getView().getZoom());
      });
    },
    resetViewer() {
      this.backHome();
      this.closeBulletChange();
    },
    zoomTo(data) {
      const to = [data.longitude, data.latitude];
      const view = this.map.getView();
      view.setZoom(18);
      view.animate({
        center: to,
        duration: 0
      });
      // 定位跳转弹窗显示
      const overlayerForm = this.map.getOverlayById("overlayerForm");
      if (overlayerForm) {
        overlayerForm.setPosition([data.longitude, data.latitude]);
        this.dataOutput = data; //将传感器信息数据传递给弹窗并显示
      }
    },
    searchHandle() {
      this.$parent.$on("handleSearchHome", data => {
        const to = [data.longitude, data.latitude];
        const view = this.map.getView();
        view.setZoom(15);
        view.animate({
          center: to,
          duration: 0
        });
      });
    },
    backHome() {
      const view = this.map.getView();
      view.setZoom(defaultZoom);
      view.setCenter(defaultCenter);
    },
    // 关闭弹窗
    closeBulletChange() {
      const bullet = this.map.getOverlayById("overlayerForm"); // 拿到地图上的弹窗图层
      bullet.setPosition(undefined);
    },
    // 通过id查找图层
    findLayerById(id) {
      const layers = this.map.getLayers();
      let res;
      layers.array_.forEach(layer => {
        if (layer.values_.id && layer.values_.id === id) {
          res = layer;
        }
      });
      return res;
    },
    // =============== 加载谷歌地图 ========================================
    handleMapInit() {
      const target = this.$refs.mapDOM;
      const map = new Map({
        target: target,
        view: new View({
          multiWorld: true,
          projection: "EPSG:4326",
          center: [85.06,42.95],
          zoom: 6,
          // extent: [
          //   64.07123046875,
          //   32.381259765625,
          //   106.25873046875,
          //   53.321201171875
          // ],
          maxZoom: 18
        }),
        controls: defaultControls({
          zoom: false, // 不显示放大放小控件
          rotate: false // 不显示指北针控件
        })
      });
      const baseLayer = new TileLayer({
        source: new XYZ({
          url:
            "https://gac-geo.googlecnapps.cn/maps/vt?lyrs=s&x={x}&y={y}&z={z}",
          crossOrigin: true
        })
      });
      baseLayer.set("id", "baseLayer");
      map.addLayer(baseLayer);
      const feature = new GeoJSON().readFeatures(BoundaryAreaJson, {
        dataProjection: "EPSG:4326",
        featureProjection: "EPSG:4326"
      })[0];
      // console.log(feature.getGeometry().)
      const outMask = new MaskFilter({
        feature: feature,
        wrapX: true,
        inner: false,
        fill: new Fill({
          color: "rgba(8, 16, 42,0.8)"
        }),
        shadowWidth: 15,
        shadowColor: "rgb(48,161,239)"
      });
      baseLayer.addFilter(outMask);
      outMask.setActive(true);
      const innerMask = new MaskFilter({
        feature: feature,
        wrapX: true,
        inner: true,
        fill: new Fill({
          color: "rgba(8, 16, 42,0)"
        }),
        shadowWidth: 15,
        shadowColor: "rgb(48,161,239)"
      });
      baseLayer.addFilter(innerMask);
      innerMask.setActive(true);
      const boundaryLayer = new VectorLayer({
        source: new VectorSource({
          features: [feature]
        })
      });
      boundaryLayer.setStyle(
        new Style({
          fill: undefined,
          stroke: new Stroke({
            color: "#fff",
            width: 5
          })
        })
      );
      map.addLayer(boundaryLayer);
      this.map = map;
      this.handleDrawSensorLayer();
      // ========================================定义弹窗组件========================================
      const overlayerForm = new Overlay({
        id: "overlayerForm", //图层id
        element: this.$refs.msgFormSensor.$el, //图层接管DOM
        autoPan: {
          //定义弹窗在边缘点击不完整，设置自动平移效果
          animation: {
            duration: 250, //自动平移效果的动画时间
          }
        },
        positioning: "top-center"
        // offset: [0, -30],
      });
      overlayerForm.setPosition(undefined);
      this.map.addOverlay(overlayerForm);
      // ========================================定义点击事件========================================
      map.on("click", e => {
        const featureSensor = [];
        const features = map.getFeaturesAtPixel(e.pixel);
        if (features.length > 0) {
          map.forEachFeatureAtPixel(e.pixel, item => {
            // 当选中目标图层时
            if (item.values_.props) {
              let mouse = e.coordinate; //鼠标点击的经纬度坐标位置
              overlayerForm.setPosition(mouse); //设置弹窗显示位置
              featureSensor.push(item);
              this.dataOutput = featureSensor[0].values_.props;
            }
          });
        } else {
          overlayerForm.setPosition(undefined); // 如果未点击到图层,不显示弹窗
        }
      });
    },
    // =============== 加载传感器点数据 ========================================
    handleDrawSensorLayer() {
      // 使用请求数据
      SensorArea().then(res => {
        if (res.code === 200) {
          // 筛选监测正常传感器数据
          const NormalFeatures = [];
          // 筛选监测异常传感器数据
          const WarningFeatures = [];
          res.data.rows.forEach(item => {
            const styleNormal = new Style({
              image: new Icon({
                anchorXUnits: "fraction",
                anchorYUnits: "fraction",
                src: require("../../../../assets/img/OneMap/正常传感器.png")
              })
            });
            const styleWarning = new Style({
              image: new Icon({
                // anchor: [0.5, 20], //图标的锚点，图标的偏移
                anchorXUnits: "fraction",
                anchorYUnits: "fraction",
                src: require("../../../../assets/img/OneMap/预警传感器.png")
              })
            });
            // 筛选监测正常和监测异常
            if (item.ifAlarm === 1 && item.ifFault === 1) {
              const NormalFeature = new Feature({
                geometry: new Point([item.longitude, item.latitude])
              });
              NormalFeature.set("props", item);
              NormalFeature.setStyle(styleNormal);
              NormalFeatures.push(NormalFeature);
            } else {
              const WarningFeature = new Feature({
                geometry: new Point([item.longitude, item.latitude])
              });
              WarningFeature.set("props", item);
              WarningFeature.setStyle(styleWarning);
              WarningFeatures.push(WarningFeature);
            }
          });
          // 单独添加正常传感器图层
          const sourceNormal = new VectorSource({
            wrapX: false,
            features: NormalFeatures
          });
          const layerNormal = new VectorLayer({
            source: sourceNormal
          });
          this.map.addLayer(layerNormal);
          // 单独添加异常传感器图层
          const sourceWarning = new VectorSource({
            wrapX: false,
            features: WarningFeatures
          });
          const layerWarning = new VectorLayer({
            source: sourceWarning
          });
          this.map.addLayer(layerWarning);
          // 找到地图：谷歌地图
          const allLayers = this.map.getLayers();
          const tileLayer = allLayers.array_[0];
          // 定义动态渲染方法
          const duration = 3000;
          const that = this; //使用当前map
          function flash(feature) {
            const start = Date.now();
            const flashGeom = feature.getGeometry().clone();
            const listenerKey = tileLayer.on("postrender", animate);
            function animate(event) {
              const frameState = event.frameState;
              const elapsed = frameState.time - start;
              if (elapsed >= duration) {
                unByKey(listenerKey);
                return;
              }
              const vectorContext = getVectorContext(event);
              const elapsedRatio = elapsed / duration;
              // radius will be 5 at start and 30 at end.
              const radius = easeOut(elapsedRatio) * 25 + 5;
              const opacity = easeOut(1 - elapsedRatio);
              const style = new Style({
                image: new CircleStyle({
                  radius: radius,
                  stroke: new Stroke({
                    color: "rgba(255, 0, 0, " + opacity + ")",
                    width: 0.25 + opacity
                  }),
                  fill: new Fill({
                    color: "rgba(255,0,0,0.3)"
                  })
                })
              });
              vectorContext.setStyle(style);
              vectorContext.drawGeometry(flashGeom);
              that.map.render();
            }
          }
          sourceWarning.on("addfeature", function(e) {
            flash(e.feature);
          });
          // 利用定时器添加监测异常图层
          intervalKey = setInterval(() => {
            sourceWarning.clear();
            sourceWarning.addFeatures(WarningFeatures);
          }, 1000);
        }
      });
    }
  }
};
</script>

<style lang="scss" scoped>
.OneMap {
  width: 100%;
  height: 100%;
  position: relative;
  .map-wrapper-1 {
    width: 100%;
    height: 100%;
  }
  .map-legend {
    position: absolute;
    left: 35px;
    bottom: 0;
    width: 166px;
    height: 90px;
    background: url("../../../../assets/img/OneMap/传感器图例.png") no-repeat;
    background-size: 100% 100%;
    z-index: 999;
    pointer-events: none;
  }
  .map-compass {
    position: absolute;
    left: 35px;
    top: 110px;
    width: 30px;
    height: 30px;
    background: url("../../../../assets/img/Home/指北针.png") no-repeat;
    background-size: 100% 100%;
    z-index: 999;
    pointer-events: none;
  }
}
</style>
<style lang="scss">
.position-bar-container-1 {
  // border: 1px solid red;
  position: absolute;
  bottom: 0;
  height: 30px;
  width: 100%;
  display: flex;
  flex-direction: row;
  align-items: center;
  font-family: "AlibabaPuHuiTi-2-85-Bold";
  font-size: 14px;
  font-weight: normal;
  font-style: italic;
  font-stretch: normal;
  letter-spacing: 1px;
  color: #bbcde6;
  text-shadow: 2px 2px 4px rgba(8, 16, 42, 1);
  #scale-line-container-1 {
    position: absolute;
    left: 900px;
    height: 100%;
    .ol-scale-line {
      bottom: 0px;
      background-color: transparent;
      .ol-scale-line-inner {
        border: 1px solid transparent;
        border-top: none;
        font-family: "AlibabaPuHuiTi-2-85-Bold";
        font-size: 14px;
        font-weight: normal;
        font-style: italic;
        font-stretch: normal;
        letter-spacing: 1px;
        color: #bbcde6;
        text-shadow: 2px 2px 4px rgba(8, 16, 42, 1);
      }
    }
  }
  .coordinate-lebel-contaienr {
    position: absolute;
    right: 70px;
    height: 30px;
    line-height: 30px;
    display: flex;
    flex-direction: row;
    width: 60%;
    align-items: center;
    justify-content: flex-end;
    .lttd-container {
      margin-left: 5%;
    }
  }
  .zoom-label-contaienr {
    position: absolute;
    right: 850px;
    height: 30px;
    line-height: 30px;
  }
}
</style>